/* eslint-disable no-prototype-builtins */
/* eslint-disable @typescript-eslint/explicit-member-accessibility */
/* eslint-disable @typescript-eslint/explicit-function-return-type */
//
//  react-native-orientation-locker
//
//
//  Created by Wonday on 17/5/12.
//  Copyright (c) wonday.org All rights reserved.
//

import { NativeEventEmitter, Platform, NativeModules } from 'react-native';

const OrientationNative = NativeModules.Orientation;
const LocalEventEmitter = new NativeEventEmitter(OrientationNative);

const listeners: { [key: string]: any } = {};

let id = 0;
const META = '__listener_id';

let locked = false;

function getKey(listener: any) {
  if (!listener.hasOwnProperty(META)) {
    if (!Object.isExtensible(listener)) {
      return 'F';
    }
    id += 1;
    Object.defineProperty(listener, META, {
      value: `L${id}`
    });
  }
  return listener[META];
}

export default class Orientation {
  static getOrientation = (cb: any) => {
    OrientationNative.getOrientation((orientation: any) => {
      cb(orientation);
    });
  };

  static getDeviceOrientation = (cb: any) => {
    OrientationNative.getDeviceOrientation((deviceOrientation: any) => {
      cb(deviceOrientation);
    });
  };

  static isLocked = () => {
    return locked;
  };

  static lockToPortrait = () => {
    locked = true;
    OrientationNative.lockToPortrait();
  };

  static lockToPortraitUpsideDown = () => {
    locked = true;
    OrientationNative.lockToPortraitUpsideDown();
  };

  static lockToLandscape = () => {
    locked = true;
    OrientationNative.lockToLandscape();
  };

  static lockToLandscapeRight = () => {
    locked = true;
    OrientationNative.lockToLandscapeRight();
  };

  static lockToLandscapeLeft = () => {
    locked = true;
    OrientationNative.lockToLandscapeLeft();
  };

  static unlockAllOrientations = () => {
    locked = false;
    OrientationNative.unlockAllOrientations();
  };

  static addOrientationListener = (cb: any) => {
    const key = getKey(cb);
    listeners[key] = LocalEventEmitter.addListener(
      'orientationDidChange',
      body => {
        cb(body.orientation);
      }
    );
  };

  static removeOrientationListener = (cb: any) => {
    const key = getKey(cb);
    if (!listeners[key]) {
      return;
    }
    listeners[key].remove();
    listeners[key] = null;
  };

  static addDeviceOrientationListener = (cb: any) => {
    const key = getKey(cb);
    listeners[key] = LocalEventEmitter.addListener(
      'deviceOrientationDidChange',
      body => {
        cb(body.deviceOrientation);
      }
    );
  };

  static removeDeviceOrientationListener = (cb: any) => {
    const key = getKey(cb);
    if (!listeners[key]) {
      return;
    }
    listeners[key].remove();
    listeners[key] = null;
  };

  static addLockListener = (cb: any) => {
    const key = getKey(cb);
    listeners[key] = LocalEventEmitter.addListener('lockDidChange', body => {
      cb(body.orientation);
    });
  };

  static removeLockListener = (cb: any) => {
    const key = getKey(cb);
    if (!listeners[key]) {
      return;
    }
    listeners[key].remove();
    listeners[key] = null;
  };

  static removeAllListeners = () => {
    // eslint-disable-next-line no-restricted-syntax
    for (const key in listeners) {
      if (!listeners[key]) {
        // eslint-disable-next-line no-continue
        continue;
      }
      listeners[key].remove();
      listeners[key] = null;
    }
  };

  static getInitialOrientation = () => {
    return OrientationNative.initialOrientation;
  };

  static getAutoRotateState = (cb: any) => {
    if (Platform.OS === 'android') {
      OrientationNative.getAutoRotateState((state: any) => {
        cb(state);
      });
    } else {
      cb(true); // iOS not implement
    }
  };
}
